package com.hk.web.core.handler;

import com.hk.commons.eunms.Enums;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.util.Assert;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//自定义mybaitis 枚举Handler
public class EnumsHandler<E extends Enums<E>> extends BaseTypeHandler<E> {

    private Class<E> type;

    public EnumsHandler(Class<E> type) {
        if (type == null)
            throw new IllegalArgumentException("Type argument cannot be null");
        this.type = type;
    }

    /**
     * 用于定义设置参数时，该如何把Java类型的参数转换为对应的数据库类型
     */
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, E tEnums, JdbcType jdbcType) throws SQLException {
        String code = String.valueOf(tEnums.getCode());
        if (jdbcType == null && code != null) {
            preparedStatement.setObject(i, code);
        } else {
            Assert.isNull(jdbcType,"jdbcType不能为空");
            preparedStatement.setObject(i, code, jdbcType.TYPE_CODE); // see r3589
        }
    }

    /**
     * 用于定义通过字段名称获取字段数据时，如何把数据库类型转换为对应的Java类型
     */
    @Override
    public E getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        Object obj = resultSet.getObject(columnName);
        return resultSet.wasNull() ? null : getEnum(obj);
    }

    /**
     * 用于定义通过字段索引获取字段数据时，如何把数据库类型转换为对应的Java类型
     */
    @Override
    public E getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        Object obj = resultSet.getObject(columnIndex);
        return resultSet.wasNull() ? null : getEnum(obj);
    }

    /**
     * 用定义调用存储过程后，如何把数据库类型转换为对应的Java类型
     */
    @Override
    public E getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        Object obj = callableStatement.getObject(columnIndex);
        return callableStatement.wasNull() ? null : getEnum(obj);
    }

    /**
     * 获得枚举值
     */
    private E getEnum(Object obj) {
        E[] enumConstants = type.getEnumConstants();
        if (null!=enumConstants){
            for (E tEnums : enumConstants) {
                String code = tEnums.getCode()+"";
                if (obj.equals(code)){
                    return tEnums;
                }
            }
        }
        throw new IllegalArgumentException(String.format("未知的枚举类型：%s,请核对%s", obj, type.getSimpleName()));
    }
}
